#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
基于最终定价策略的智能扩缩容策略
支持安卓订阅模式和iOS次数包模式的差异化扩缩容
"""

import time
import json
import logging
from datetime import datetime, timedelta
from typing import Dict, List, Tuple, Optional
from dataclasses import dataclass
from enum import Enum
import statistics

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class UserPlatform(Enum):
    """用户平台枚举"""
    ANDROID = "android"
    IOS = "ios"
    OTHER = "other"

class UserTier(Enum):
    """用户等级枚举"""
    FREE = "free"
    # 安卓订阅用户
    ANDROID_BASIC = "android_basic"
    ANDROID_STANDARD = "android_standard"
    ANDROID_PRO = "android_pro"
    ANDROID_ENTERPRISE = "android_enterprise"
    # iOS次数包用户
    IOS_BASIC = "ios_basic"
    IOS_STANDARD = "ios_standard"
    IOS_ADVANCED = "ios_advanced"
    IOS_PROFESSIONAL = "ios_professional"

class ProcessingPriority(Enum):
    """处理优先级"""
    FREE_USER = 1
    IOS_BASIC = 2
    ANDROID_BASIC = 3
    IOS_STANDARD = 4
    ANDROID_STANDARD = 5
    IOS_ADVANCED = 6
    ANDROID_PRO = 7
    IOS_PROFESSIONAL = 8
    ANDROID_ENTERPRISE = 9

@dataclass
class UserInfo:
    """用户信息"""
    user_id: str
    platform: UserPlatform
    tier: UserTier
    subscription_status: str  # active, expired, cancelled
    remaining_quota: int
    priority: ProcessingPriority
    last_activity: datetime

@dataclass
class ScalingMetrics:
    """扩缩容指标"""
    timestamp: datetime
    queue_length: int
    free_queue_length: int
    android_subscription_queue: int
    ios_usage_queue: int
    average_wait_time: float
    cpu_utilization: float
    gpu_utilization: float
    current_instances: int
    user_distribution: Dict[UserTier, int]
    platform_distribution: Dict[UserPlatform, int]
    revenue_per_hour: float
    cost_per_hour: float

@dataclass
class ScalingDecision:
    """扩缩容决策"""
    action: str  # scale_out, scale_in, maintain
    target_instances: int
    reason: str
    confidence: float
    estimated_cost_impact: float
    priority_users_affected: List[UserTier]
    execution_time: datetime

class UpdatedScalingStrategy:
    """基于最终定价策略的智能扩缩容策略"""
    
    def __init__(self):
        self.config = self._load_config()
        self.user_manager = UserManager()
        self.cost_optimizer = CostOptimizer()
        
    def _load_config(self) -> Dict:
        """加载配置"""
        return {
            'scaling_thresholds': {
                # 免费用户阈值 - 基于性能测试优化
                'free_user': {
                    'scale_out': {
                        'queue_length': 5,   # 降低队列阈值，更积极扩容
                        'wait_time': 0.1,    # 100ms，基于实际平均处理时间31ms
                    },
                    'scale_in': {
                        'queue_length': 1,   # 更积极的缩容
                        'wait_time': 0.05,   # 50ms，基于实际性能
                    },
                    'min_instances': 1,  # 最少1个实例，支持24小时不间断运行
                    'cooldown_period': 30,  # 缩短冷却期
                },
                # 安卓订阅用户阈值 - 基于性能测试优化
                'android_subscription': {
                    'scale_out': {
                        'queue_length': 3,   # 保持较低阈值
                        'wait_time': 0.1,    # 100ms，基于实际性能
                    },
                    'scale_in': {
                        'queue_length': 1,   # 更积极的缩容
                        'wait_time': 0.05,   # 50ms，基于实际性能
                    },
                    'cooldown_period': 10,  # 更快的响应
                },
                # iOS次数包用户阈值 - 基于性能测试优化
                'ios_usage': {
                    'scale_out': {
                        'queue_length': 3,   # 保持较低阈值
                        'wait_time': 0.1,    # 100ms，基于实际性能
                    },
                    'scale_in': {
                        'queue_length': 1,   # 更积极的缩容
                        'wait_time': 0.05,   # 50ms，基于实际性能
                    },
                    'cooldown_period': 10,  # 更快的响应
                }
            },
            'priority_weights': {
                UserTier.FREE: 1,
                UserTier.ANDROID_BASIC: 3,  # 安卓和iOS同等优先级
                UserTier.IOS_BASIC: 3,
                UserTier.ANDROID_STANDARD: 4,
                UserTier.IOS_STANDARD: 4,
                UserTier.ANDROID_PRO: 5,
                UserTier.IOS_ADVANCED: 5,
                UserTier.ANDROID_ENTERPRISE: 6,
                UserTier.IOS_PROFESSIONAL: 6,
            },
            'cost_control': {
                'max_daily_cost': 100,  # 每日最大成本100元
                'target_profit_margin': 0.7,  # 目标利润率70%
                'free_quota_utilization': {
                    'disk_limit_gb': 80,
                    'network_limit_gb': 500,
                }
            },
            'platform_preferences': {
                'android_subscription_priority': 1,  # 安卓和iOS同等优先级
                'ios_usage_priority': 1,
                'free_user_priority': 2,
            },
            'scaling_optimization': {
                'fast_scale_in': True,  # 快速缩容，避免空闲实例
                'scale_in_delay': 30,   # 30秒后开始缩容
                'idle_instance_threshold': 60,  # 60秒空闲后销毁实例
                'min_free_instances': 1,  # 免费用户最少保持1个实例
            }
        }
    
    def analyze_scaling_need(self, metrics: ScalingMetrics) -> ScalingDecision:
        """分析扩缩容需求"""
        # 1. 分析用户分布和优先级
        priority_analysis = self._analyze_user_priority(metrics)
        
        # 2. 分析成本效益
        cost_analysis = self._analyze_cost_benefit(metrics)
        
        # 3. 分析负载情况
        load_analysis = self._analyze_load_distribution(metrics)
        
        # 4. 生成扩缩容决策
        decision = self._generate_scaling_decision(
            metrics, priority_analysis, cost_analysis, load_analysis
        )
        
        return decision
    
    def _analyze_user_priority(self, metrics: ScalingMetrics) -> Dict:
        """分析用户优先级"""
        total_users = sum(metrics.user_distribution.values())
        if total_users == 0:
            return {'priority_score': 0, 'high_value_users': 0}
        
        # 计算优先级分数
        priority_score = 0
        high_value_users = 0
        
        for tier, count in metrics.user_distribution.items():
            weight = self.config['priority_weights'].get(tier, 1)
            priority_score += (count / total_users) * weight
            
            # 统计高价值用户（订阅用户和高级次数包用户）
            if tier in [UserTier.ANDROID_STANDARD, UserTier.ANDROID_PRO, 
                       UserTier.ANDROID_ENTERPRISE, UserTier.IOS_ADVANCED, 
                       UserTier.IOS_PROFESSIONAL]:
                high_value_users += count
        
        return {
            'priority_score': priority_score,
            'high_value_users': high_value_users,
            'high_value_ratio': high_value_users / total_users if total_users > 0 else 0
        }
    
    def _analyze_cost_benefit(self, metrics: ScalingMetrics) -> Dict:
        """分析成本效益"""
        # 计算当前利润率
        if metrics.revenue_per_hour > 0:
            current_profit_margin = (metrics.revenue_per_hour - metrics.cost_per_hour) / metrics.revenue_per_hour
        else:
            current_profit_margin = 0
        
        # 计算目标成本
        target_cost = metrics.revenue_per_hour * (1 - self.config['cost_control']['target_profit_margin'])
        
        # 分析成本控制需求
        cost_control_needed = metrics.cost_per_hour > target_cost
        
        return {
            'current_profit_margin': current_profit_margin,
            'target_profit_margin': self.config['cost_control']['target_profit_margin'],
            'cost_control_needed': cost_control_needed,
            'target_cost': target_cost,
            'cost_efficiency': metrics.revenue_per_hour / metrics.cost_per_hour if metrics.cost_per_hour > 0 else 0
        }
    
    def _analyze_load_distribution(self, metrics: ScalingMetrics) -> Dict:
        """分析负载分布"""
        # 分析各平台负载
        android_load = metrics.android_subscription_queue
        ios_load = metrics.ios_usage_queue
        free_load = metrics.free_queue_length
        
        total_load = android_load + ios_load + free_load
        
        # 计算负载分布
        load_distribution = {
            'android_ratio': android_load / total_load if total_load > 0 else 0,
            'ios_ratio': ios_load / total_load if total_load > 0 else 0,
            'free_ratio': free_load / total_load if total_load > 0 else 0,
        }
        
        # 分析负载优先级
        priority_load = android_load * 3 + ios_load * 2 + free_load * 1
        
        return {
            'load_distribution': load_distribution,
            'priority_load': priority_load,
            'total_load': total_load,
            'load_imbalance': max(load_distribution.values()) - min(load_distribution.values())
        }
    
    def _generate_scaling_decision(self, metrics: ScalingMetrics, 
                                 priority_analysis: Dict, cost_analysis: Dict, 
                                 load_analysis: Dict) -> ScalingDecision:
        """生成扩缩容决策"""
        # 基础实例数计算
        base_instances = max(1, int(metrics.queue_length / 5))
        
        # 优先级调整
        priority_multiplier = 1 + (priority_analysis['priority_score'] - 1) * 0.3
        
        # 高价值用户调整
        high_value_multiplier = 1 + priority_analysis['high_value_ratio'] * 0.5
        
        # 负载调整
        load_multiplier = 1 + (load_analysis['priority_load'] / 100) * 0.4
        
        # 计算目标实例数
        target_instances = int(base_instances * priority_multiplier * 
                             high_value_multiplier * load_multiplier)
        
        # 应用最小实例限制（免费用户最少1个实例）
        min_instances = self._get_min_instances_for_platforms(metrics.platform_distribution)
        target_instances = max(target_instances, min_instances)
        
        # 成本控制调整
        if cost_analysis['cost_control_needed']:
            target_instances = max(1, target_instances // 2)
        
        # 生成决策
        if target_instances > metrics.current_instances:
            action = 'scale_out'
            reason = f"负载增加，高价值用户比例 {priority_analysis['high_value_ratio']:.1%}"
            confidence = min(0.9, 0.5 + priority_analysis['priority_score'] * 0.1)
        elif target_instances < metrics.current_instances and not cost_analysis['cost_control_needed']:
            action = 'scale_in'
            reason = f"负载降低，成本优化"
            confidence = min(0.9, 0.5 + (1 - priority_analysis['priority_score']) * 0.1)
        else:
            action = 'maintain'
            reason = "负载平衡，无需调整"
            confidence = 0.8
        
        # 计算成本影响
        cost_impact = (target_instances - metrics.current_instances) * 1.2  # 每小时1.2元
        
        # 确定受影响的优先级用户
        affected_users = self._get_affected_priority_users(metrics.user_distribution)
        
        return ScalingDecision(
            action=action,
            target_instances=target_instances,
            reason=reason,
            confidence=confidence,
            estimated_cost_impact=cost_impact,
            priority_users_affected=affected_users,
            execution_time=datetime.now()
        )
    
    def _get_min_instances_for_platforms(self, platform_distribution: Dict[UserPlatform, int]) -> int:
        """根据平台分布计算最小实例数"""
        min_instances = 0
        
        for platform, count in platform_distribution.items():
            if count > 0:
                if platform == UserPlatform.ANDROID:
                    # 安卓用户不设置最大限制，但确保快速缩容
                    min_instances += 0
                elif platform == UserPlatform.IOS:
                    # iOS用户不设置最大限制，但确保快速缩容
                    min_instances += 0
                else:
                    # 免费用户最少保持1个实例
                    min_instances += self.config['scaling_thresholds']['free_user']['min_instances']
        
        return min_instances
    
    def _get_affected_priority_users(self, user_distribution: Dict[UserTier, int]) -> List[UserTier]:
        """获取受影响的优先级用户"""
        # 按优先级排序用户类型
        sorted_users = sorted(user_distribution.items(), 
                            key=lambda x: self.config['priority_weights'].get(x[0], 1), 
                            reverse=True)
        
        # 返回前3个优先级最高的用户类型
        return [user_tier for user_tier, count in sorted_users[:3] if count > 0]
    
    def get_platform_specific_scaling(self, platform: UserPlatform, 
                                    queue_length: int, wait_time: float) -> Dict:
        """获取平台特定的扩缩容策略"""
        if platform == UserPlatform.ANDROID:
            config = self.config['scaling_thresholds']['android_subscription']
        elif platform == UserPlatform.IOS:
            config = self.config['scaling_thresholds']['ios_usage']
        else:
            config = self.config['scaling_thresholds']['free_user']
        
        # 判断是否需要扩缩容
        should_scale_out = (queue_length >= config['scale_out']['queue_length'] or 
                          wait_time >= config['scale_out']['wait_time'])
        
        should_scale_in = (queue_length <= config['scale_in']['queue_length'] and 
                         wait_time <= config['scale_in']['wait_time'])
        
        return {
            'should_scale_out': should_scale_out,
            'should_scale_in': should_scale_in,
            'min_instances': config.get('min_instances', 0),
            'cooldown_period': config['cooldown_period'],
            'config': config
        }
    
    def optimize_for_revenue(self, metrics: ScalingMetrics) -> Dict:
        """为收入优化扩缩容策略"""
        # 分析收入贡献
        revenue_analysis = {
            'android_revenue': self._calculate_android_revenue(metrics.user_distribution),
            'ios_revenue': self._calculate_ios_revenue(metrics.user_distribution),
            'total_revenue': 0,
            'revenue_per_instance': 0
        }
        
        revenue_analysis['total_revenue'] = (revenue_analysis['android_revenue'] + 
                                           revenue_analysis['ios_revenue'])
        
        if metrics.current_instances > 0:
            revenue_analysis['revenue_per_instance'] = (revenue_analysis['total_revenue'] / 
                                                      metrics.current_instances)
        
        # 优化建议
        optimization_suggestions = []
        
        if revenue_analysis['android_revenue'] > revenue_analysis['ios_revenue'] * 2:
            optimization_suggestions.append("安卓用户收入占主导，优先保障安卓用户服务")
        
        if revenue_analysis['revenue_per_instance'] < 5:  # 每小时5元
            optimization_suggestions.append("单实例收入较低，考虑缩容优化")
        
        if metrics.free_queue_length > metrics.queue_length * 0.5:
            optimization_suggestions.append("免费用户占比过高，考虑引导付费")
        
        return {
            'revenue_analysis': revenue_analysis,
            'optimization_suggestions': optimization_suggestions
        }
    
    def _calculate_android_revenue(self, user_distribution: Dict[UserTier, int]) -> float:
        """计算安卓用户收入"""
        revenue = 0
        android_tiers = [UserTier.ANDROID_BASIC, UserTier.ANDROID_STANDARD, 
                        UserTier.ANDROID_PRO, UserTier.ANDROID_ENTERPRISE]
        
        tier_prices = {
            UserTier.ANDROID_BASIC: 19,
            UserTier.ANDROID_STANDARD: 49,
            UserTier.ANDROID_PRO: 99,
            UserTier.ANDROID_ENTERPRISE: 199
        }
        
        for tier in android_tiers:
            if tier in user_distribution:
                revenue += user_distribution[tier] * tier_prices[tier]
        
        return revenue
    
    def _calculate_ios_revenue(self, user_distribution: Dict[UserTier, int]) -> float:
        """计算iOS用户收入"""
        revenue = 0
        ios_tiers = [UserTier.IOS_BASIC, UserTier.IOS_STANDARD, 
                    UserTier.IOS_ADVANCED, UserTier.IOS_PROFESSIONAL]
        
        tier_prices = {
            UserTier.IOS_BASIC: 5,
            UserTier.IOS_STANDARD: 20,
            UserTier.IOS_ADVANCED: 60,
            UserTier.IOS_PROFESSIONAL: 200
        }
        
        for tier in ios_tiers:
            if tier in user_distribution:
                revenue += user_distribution[tier] * tier_prices[tier]
        
        return revenue

class UserManager:
    """用户管理器"""
    
    def __init__(self):
        self.user_cache = {}
    
    def get_user_info(self, user_id: str) -> Optional[UserInfo]:
        """获取用户信息"""
        return self.user_cache.get(user_id)
    
    def update_user_activity(self, user_id: str, platform: UserPlatform, 
                           tier: UserTier, remaining_quota: int):
        """更新用户活动"""
        user_info = UserInfo(
            user_id=user_id,
            platform=platform,
            tier=tier,
            subscription_status='active',
            remaining_quota=remaining_quota,
            priority=self._get_priority_for_tier(tier),
            last_activity=datetime.now()
        )
        
        self.user_cache[user_id] = user_info
    
    def _get_priority_for_tier(self, tier: UserTier) -> ProcessingPriority:
        """根据用户等级获取优先级"""
        priority_mapping = {
            UserTier.FREE: ProcessingPriority.FREE_USER,
            UserTier.ANDROID_BASIC: ProcessingPriority.ANDROID_BASIC,
            UserTier.IOS_BASIC: ProcessingPriority.IOS_BASIC,
            UserTier.ANDROID_STANDARD: ProcessingPriority.ANDROID_STANDARD,
            UserTier.IOS_STANDARD: ProcessingPriority.IOS_STANDARD,
            UserTier.ANDROID_PRO: ProcessingPriority.ANDROID_PRO,
            UserTier.IOS_ADVANCED: ProcessingPriority.IOS_ADVANCED,
            UserTier.ANDROID_ENTERPRISE: ProcessingPriority.ANDROID_ENTERPRISE,
            UserTier.IOS_PROFESSIONAL: ProcessingPriority.IOS_PROFESSIONAL,
        }
        
        return priority_mapping.get(tier, ProcessingPriority.FREE_USER)

class CostOptimizer:
    """成本优化器"""
    
    def __init__(self):
        self.cost_history = []
    
    def calculate_optimal_instances(self, revenue: float, target_margin: float) -> int:
        """计算最优实例数"""
        # 基于收入和目标利润率计算最优实例数
        target_cost = revenue * (1 - target_margin)
        optimal_instances = max(1, int(target_cost / 1.2))  # 每小时1.2元成本
        
        return optimal_instances
    
    def analyze_cost_trend(self) -> Dict:
        """分析成本趋势"""
        if len(self.cost_history) < 2:
            return {'trend': 'insufficient_data'}
        
        recent_costs = [record['cost'] for record in self.cost_history[-10:]]
        trend = statistics.mean(recent_costs[-3:]) - statistics.mean(recent_costs[:3])
        
        return {
            'trend': 'increasing' if trend > 0 else 'decreasing',
            'trend_magnitude': abs(trend),
            'average_cost': statistics.mean(recent_costs)
        }

# 使用示例
def main():
    """使用示例"""
    strategy = UpdatedScalingStrategy()
    
    # 模拟指标
    metrics = ScalingMetrics(
        timestamp=datetime.now(),
        queue_length=25,
        free_queue_length=10,
        android_subscription_queue=10,
        ios_usage_queue=5,
        average_wait_time=120,
        cpu_utilization=75,
        gpu_utilization=80,
        current_instances=3,
        user_distribution={
            UserTier.FREE: 10,
            UserTier.ANDROID_BASIC: 5,
            UserTier.ANDROID_STANDARD: 3,
            UserTier.IOS_BASIC: 4,
            UserTier.IOS_STANDARD: 2,
        },
        platform_distribution={
            UserPlatform.ANDROID: 8,
            UserPlatform.IOS: 6,
        },
        revenue_per_hour=50.0,
        cost_per_hour=15.0
    )
    
    # 分析扩缩容需求
    decision = strategy.analyze_scaling_need(metrics)
    print(f"扩缩容决策: {decision}")
    
    # 收入优化分析
    revenue_analysis = strategy.optimize_for_revenue(metrics)
    print(f"收入分析: {revenue_analysis}")

if __name__ == '__main__':
    main()
